home *** CD-ROM | disk | FTP | other *** search
- {
- From: SKYBLU::ENNS 5-FEB-1988 22:17
- To: LOWEY
- Subj: surf fix
-
- This fix performs the shading calculations without converting them to
- normalized coordinates first. This speeds up the shading calculations
- but still provide the same results.
-
- Provided to Kevin Lowey by Steve Enns of the University of Saskatchewan,
-
- ENNS@SASK.BITNET
- }
-
- { type vector = array[1..3] of real; }
-
- procedure NORMAL (var V: vector);
- { normalize the vector V }
- var Vmag: real; { magnitude of the vector }
- J: integer; { index }
- begin
- Vmag := sqrt (sqr (V[1]) + sqr (V[2]) + sqr (V[3]) );
- if (Vmag > 0.0) then
- for J := 1 to 3 do
- V[J] := V[J] / Vmag;
- end; { procedure NORMAL }
-
- function POWER (X, P: real): real;
- { Raise real number X to the power P }
- begin
- if (X > 0) then
- if (P > 0) then
- POWER := exp (P * ln(X))
- else if (P = 0) then
- POWER := 1.0
- else
- POWER := 1.0 / exp (-P * ln(X))
- else if (X = 0) then
- POWER := 0.0
- else
- { Forget the negatives; aren't dealing with complex nos. }
- POWER := 0.0;
- end; { function POWER }
-
- { Common variable for SETSHADE and SHADING }
- var S: array[1..MAXLITE] of vector; { light source vectors }
-
- procedure SETSHADE;
- { Set up the light source vectors for the shading routine }
- var Lite: integer;
- J: integer;
-
- begin
- for Lite := 1 to Nlite do begin
- S[Lite][1] := Xlite[Lite] - Xfocal;
- S[Lite][2] := Ylite[Lite] - Yfocal;
- S[Lite][3] := Zlite[Lite] - Zfocal;
- normal (S[Lite]);
- end;
- end; { procedure SETSHADE }
-
- function SHADING (Surf, Side: integer): real;
- { Calculate the shade of surface Surf at point (X,Y,Z).
- (Returns a negative shade if surface is totally invisible
- [facing away from eye] )
- Side 1 is the primary side of the surface (assumes the nodes are
- numbered counter-clockwise when viewed from the outside of the
- surface). Side 2 is the inside, necessary for viewing surfaces
- that can be seen from either side (such as function plots).
- }
- var A: vector; { vector from 1st to 2nd node of surface }
- B: vector; { vector from 1st to 3rd node of surface }
- N: vector; { vector normal to surface }
- E: vector; { vector from 1st node to eye }
- D: vector; { difference from source to surface normal }
- R: vector; { vector from 1st node to reflected light }
- J: integer; { index }
- Node1: integer; { 1st node # }
- Node2: integer; { 2nd node # }
- Node3: integer; { 3rd node # }
- Vmag: real; { magnitude of vector, reflected lite to eye }
- Cumshade: real; { cumulative shade (from multiple light sources)}
- Lite: integer; { light source number }
- CosN: real; { cosine of angle from light to surface normal }
- CosS: real; { cosine of angle from reflected light to eye }
-
- begin
- {$ifdef BIGMEM}
- with ptra^ do with ptrb^ do with ptrc^ do with ptri^ do
- begin
- {$endif}
- if (Side = 1) then begin
- Node1 := Konnec (Surf, 1);
- Node2 := Konnec (Surf, 2);
- Node3 := Konnec (Surf, 3);
- end else begin
- Node1 := Konnec (Surf, 1);
- Node2 := Konnec (Surf, 3);
- Node3 := Konnec (Surf, 2);
- end;
- A[1] := Xworld[Node2] - Xworld[Node1];
- A[2] := Yworld[Node2] - Yworld[Node1];
- A[3] := Zworld[Node2] - Zworld[Node1];
- B[1] := Xworld[Node3] - Xworld[Node1];
- B[2] := Yworld[Node3] - Yworld[Node1];
- B[3] := Zworld[Node3] - Zworld[Node1];
-
- { Vector cross product N = A X B }
- N[1] := A[2]*B[3] - A[3]*B[2];
- N[2] := A[3]*B[1] - A[1]*B[3];
- N[3] := A[1]*B[2] - A[2]*B[1];
- normal(N);
-
- E[1] := Xeye - Xworld[Node1];
- E[2] := Yeye - Yworld[Node1];
- E[3] := Zeye - Zworld[Node1];
- normal(E);
-
- { Is surface visible to eye? }
- if (E[1]*N[1] + E[2]*N[2] + E[3]*N[3] < 0.0) then
- Shading := -1.0
- else begin
- Cumshade := Ambient[Matl[Surf]];
- for Lite := 1 to Nlite do begin
- for J := 1 to 3 do
- D[J] := S[Lite][J] - N[J];
- { Does surface face away from light source? }
- CosN := S[Lite][1]*N[1] + S[Lite][2]*N[2] + S[Lite][3]*N[3];
- if (CosN < 0.0) then
- { Cumshade := Cumshade + 0.0;} { this light source doesn't contribute}
- else begin
- for J := 1 to 3 do
- R[J] := N[J] - D[J];
- normal(R);
- { Find magnitude of vector from reflected light to eye (divided by 2) }
- Vmag := sqrt (sqr(E[1]-R[1]) + sqr(E[2]-R[2]) + sqr(E[3]-R[3])) / 2.0;
- if (Vmag > 1.0) then
- Vmag := 1.0;
- CosS := 1.0 - sqr(Vmag);
- Cumshade := Cumshade + Intensity[Lite] * (R1[Matl[Surf]] *
- power(CosS, R2[Matl[Surf]]) + R3[Matl[Surf]] * CosN);
- end; { if sqr(D[1]... }
- end; { for Lite }
- Shading := Cumshade;
- end; { if sqr(E[1]... }
- {$ifdef BIGMEM}
- end; {with}
- {$endif}
- end; { function SHADING }
-
- function VISIBLE (Surf, Side: integer): boolean;
- { Determine visibility of surface #Surf. If visible, return TRUE.
- If invisible, return FALSE.
- }
- var A: vector; { vector from 1st to 2nd node of surface }
- B: vector; { vector from 1st to 3rd node of surface }
- N: vector; { vector normal to surface }
- E: vector; { vector from 1st node to eye }
- Node1: integer; { 1st node # }
- Node2: integer; { 2nd node # }
- Node3: integer; { 3rd node # }
-
- begin
- {$ifdef BIGMEM}
- with ptra^ do with ptrb^ do with ptrc^ do
- begin
- {$endif}
-
- if (Side = 1) then begin
- Node1 := Konnec (Surf, 1);
- Node2 := Konnec (Surf, 2);
- Node3 := Konnec (Surf, 3);
- end else begin
- Node1 := Konnec (Surf, 3);
- Node2 := Konnec (Surf, 2);
- Node3 := Konnec (Surf, 1);
- end;
- A[1] := Xworld[Node2] - Xworld[Node1];
- A[2] := Yworld[Node2] - Yworld[Node1];
- A[3] := Zworld[Node2] - Zworld[Node1];
- B[1] := Xworld[Node3] - Xworld[Node1];
- B[2] := Yworld[Node3] - Yworld[Node1];
- B[3] := Zworld[Node3] - Zworld[Node1];
-
- { Vector cross product N = A X B }
- N[1] := A[2]*B[3] - A[3]*B[2];
- N[2] := A[3]*B[1] - A[1]*B[3];
- N[3] := A[1]*B[2] - A[2]*B[1];
- { normal(N); ******* Not required }
-
- E[1] := Xeye - Xworld[Node1];
- E[2] := Yeye - Yworld[Node1];
- E[3] := Zeye - Zworld[Node1];
- { normal(E); ******* Not required }
-
- { Is surface visible to eye? }
- if (E[1]*N[1] + E[2]*N[2] + E[3]*N[3] < 0.0) then
- Visible := FALSE
- else
- Visible := TRUE;
- {$ifdef BIGMEM}
- end; {with}
- {$endif}
- end; { function VISIBLE }